Skip to content

使用 Git clone depth 提速

bash
git clone https://github.com/vuejs/vue.git --depth 1
  • Git 使用一种称为“深度克隆”的技术来实现 --depth 1 选项。深度克隆是一种克隆存储库的技术,它只克隆最新的提交,而不是整个历史记录。它通过在克隆命令中使用 --depth 选项来实现。
  • git clone --depth 1 是一个用于从远程仓库克隆代码的命令,其中的 --depth 1 参数表示只克隆最新的一次提交,而不会克隆整个历史记录。这种方式可以帮助减少克隆代码所需的时间和空间。

为什么要使用 --depth 1

在日常开发中,我们通常只需要最新的代码,而不需要整个历史记录。如果不使用 --depth 1,那么 Git 会把整个历史记录都克隆下来,这样会增加克隆的时间和空间。

  • 只下载最新提交: 使用 --depth 1 选项时,Git 只会克隆最新的一次提交的相关对象和引用,而不是整个历史记录。这就意味着只需要下载最新的代码快照,而不是整个仓库的所有历史。
  • 不会克隆所有分支: 使用 --depth 1 选项时,Git 只会克隆默认分支的最新提交。如果要克隆其他分支,你需要先转到一个正常的分支。

优点

  • 速度快: 由于只克隆最新的提交,而不是整个历史记录,因此克隆速度更快。这对于大型存储库和慢速网络连接特别有用。
  • 占用空间少: 由于只包含最新的提交,所以占用的磁盘空间更小。这对于只关心最新状态的用户来说是一个优点。
  • 减少网络流量: 仅下载最新的提交,减少了克隆时的网络流量。这对于有限的网络带宽和需要快速获取存储库的用户来说很有帮助。

缺点

  • 无法访问历史记录: 最显著的缺点是,由于只克隆了最新的提交,用户将无法访问存储库的完整历史记录。这对于需要查看过去提交、分支历史或执行类似 git blame 这样的操作的用户可能是一个问题。
  • 无法切换到其他分支: 克隆深度为 1 的存储库默认会创建“detached HEAD”状态,这意味着你不能直接在克隆的存储库上创建分支。你需要先转到一个正常的分支。
  • 无法进行某些 Git 操作: 由于缺少历史记录,某些 Git 操作,如 git loggit bisect 等,可能受到限制。
  • 不适合贡献者: 对于希望为项目做贡献的人来说,克隆深度为 1 的存储库可能不够,因为他们通常需要完整的历史记录来创建和提交补丁。

拉取完整存储库

  • 使用 --depth 1 选项克隆存储库,后面使用 git pull 命令也下载不了历史 commit,只能下载最新的 commit。
  • 使用 unshallow 命令可以将深度克隆的存储库转换为完整的存储库。它会将存储库转换为完整的存储库,包括所有历史记录和分支。
bash
# 从远程仓库获取缺失的对象和引用,将仓库转换为完整存储库
git fetch --unshallow
# 如果需要,可以使用以下命令拉取所有分支的数据
git fetch --all
# 将本地仓库更新到完整状态
git pull --all

拉取指定分支

bash
git clone --depth 1 --branch <branch> <remote_repo>

原理

基本概念

Git 是一个分布式版本控制系统,它的工作原理涉及到对象 (objects)、引用 (refs) 、索引 (index) 、分支 (branch)、标签 (tag) 、提交 (commit) 、树 (tree) 和 HEAD 等概念。

  • 对象 (objects): Git 仓库中的所有数据都存储在对象中。对象是 Git 中的基本数据单元,它们包含存储在仓库中的所有文件的内容。对象可以是文件、目录、提交、分支等。
  • 引用 (refs): 引用是指向对象的指针。它们是指向对象的指针,可以是分支 (branch)、标签 (tag) 或远程跟踪分支 (remote-tracking branch)。
  • 索引 (index): 索引是一个二进制文件,它包含 Git 仓库中所有文件的元数据。它包含文件名、文件的 SHA-1 哈希值、文件的类型和文件的位置等信息。
  • 分支 (branch): 分支是指向提交 (commit) 的引用 (refs)。它们是指向提交的指针,它们指向存储在仓库中的提交对象。
  • 标签 (tag): 标签是指向提交 (commit) 的引用 (refs)。它们是指向提交的指针,它们指向存储在仓库中的提交对象。
  • 提交 (commit): 提交是 Git 中的基本数据单元。它们包含提交的作者、提交的提交者、提交的消息、提交的时间戳、提交的父提交、提交的树对象等信息。
  • 树 (tree): 树是指向文件和目录的引用 (refs)。它们是指向文件和目录的指针,它们指向存储在仓库中的树对象。
  • HEAD: HEAD 是指向当前分支 (branch) 的引用 (refs)。它是指向当前分支的指针,它指向存储在仓库中的分支对象。

对象存储

  • Git 保存信息的核心是通过对象存储,将所有的数据和元信息存储为对象。

  • 对象 (objects): Git 使用一个称为对象存储的数据库来保存所有的数据。这个数据库包含了被称为 Git 对象的文件。每个 Git 对象都有一个唯一的 SHA-1 标识符,该标识符是根据对象内容计算得出的。对象存储包括以下类型的对象:

    • blob 对象: blob 对象存储文件数据,它们是不可修改的,因此每次修改文件时都会创建一个新的 blob 对象。
    • tree 对象: tree 对象存储目录数据,它们包含一个或多个 blob 对象和其他 tree 对象的引用。
    • commit 对象: commit 对象存储提交数据,它们包含提交的作者、提交的提交者、提交的消息、提交的时间戳、提交的父提交、提交的树对象等信息。

img

  • 以一个 commit 为入口,关联的所有的 tree blob,就是这个 commit 的内容。
  • commit 之间相互关联,而 headbranchtag 等是指向具体 commit 的指针。可以在 .git/refs 下看到。这样就基于 commit 实现了 branchtag 等概念。
  • git 就是通过这三个对象来实现的版本管理和分支切换的功能,所有 objects 可以在 .git/objects 下看到。

下载单个 commit

img

  • 这样依然基于那个 commit 创建新的 commit,关联新的 blobtree 等。
  • 但是历史的 committreeblob 因为都没有下载下来所以无法切回去,相应的 tagbranch 等指针也不行。

参考